-module(fileupdate).
-export([start/3]).
-import(erlang, [display/1]).

% Not to be called externally!
-export([loop/3, getLocalProbability/3]).

start(Neighbors, FragId, FloatList) ->
	random:seed(now()),
	io:format("Starting gossip loop for updating fragment ~p~n", [FragId]),
	loop(Neighbors, FragId, FloatList),
	Random = random:uniform(),
	Prob = getLocalProbability(Neighbors, Neighbors, 0),
	if
		Random =< Prob ->
			io:format("Talking to myself~n"),
			start(Neighbors, FragId, FloatList);
		true ->
			io:format("Not talking to myself ~p ~p~n", [Random, Prob]),
			ok
	end.

loop([], _FragId, _FloatList) ->
	ok;

loop(Neighbors, FragId, FloatList) ->
	ToTalkTo = hd(Neighbors),
	case talkToNeighbor(Neighbors, ToTalkTo) of
		true ->
			io:format("Talking to node ~p~n", [ToTalkTo]),
			ToTalkTo ! {update, FragId, FloatList},
			loop(tl(Neighbors), FragId, FloatList);
		_Other ->
			loop(tl(Neighbors), FragId, FloatList)
	end,
	ok.

getLocalProbability([], _MyNeighbors, Sum) ->
	1.0 - Sum;
getLocalProbability(ToCalculate, MyNeighbors, Sum) ->
	getLocalProbability(
	      tl(ToCalculate),
				MyNeighbors,
				Sum + getProbability(MyNeighbors, hd(ToCalculate))).
	

getProbability(MyNeighbors, Neighbor) ->
	Neighbor ! {sizeN, self()},
	NumNRndmNode = popMessage(),
	MyNumNodes = length(MyNeighbors),
	1.0 / (1.0 + erlang:max(MyNumNodes, NumNRndmNode)).

talkToNeighbor(MyNeighbors, Neighbor) ->	
	Random = random:uniform(),
	Prob = getProbability(MyNeighbors, Neighbor),
	if
		Random =< Prob -> true;
		true -> false
	end.
  
popMessage() ->
	receive
		Msg -> Msg
	end.
    
